﻿using System;
using System.Collections.Generic;

namespace CxExtension
{
	/// <summary>
	/// 表堆栈,用于实现表的继承,当要查询某个key时,先查找栈顶的表,然后依次查询
	/// </summary>
	/// <typeparam name="K"></typeparam>
	/// <typeparam name="V"></typeparam>
	public class TableStack<K, V>
	{
		private readonly List<IDictionary<K, V>> mTables=new List<IDictionary<K, V>>();
		public List<IDictionary<K, V>> Tables { get { return mTables; } }

		public TableStack()
		{
		}

		public TableStack(IEnumerable<IDictionary<K,V>> enumerable):this()
		{
			mTables.AddRange(enumerable);
		}

		/// <summary>
		/// 获取某个key的值,执行堆栈原则,先查找末尾的表
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public V Get(K key)
		{
			var v = default(V);
			ForeachRever(key, (it, k) =>
			{
				if (!it.ContainsKey(k)) return false;

				v = it[k];
				return true;

			});
			return v;
		}

		/// <summary>
		/// push一个表
		/// </summary>
		/// <param name="value"></param>
		public void Push(IDictionary<K, V> value)
		{
			mTables.Add(value);
		}

		public void Pop(IDictionary<K, V> value)
		{
			mTables.Remove(value);
		}

		/// <summary>
		/// 反向遍历list的所有表
		/// </summary>
		/// <param name="key"></param>
		/// <param name="action"></param>
		/// <returns></returns>
		public bool ForeachRever(K key, Func<IDictionary<K, V>, K, bool> action)
		{
			for(var i = mTables.Count - 1; i >= 0; i--)
			{
				var it = mTables[i];
				if(it == null)
				{
					continue;
				}

				if(action(it, key))
				{
					return true;
				}
			}

			return false;
		}

		/// <summary>
		/// 检测是否存在某个键
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public bool ContainsKey(K key)
		{
			return ForeachRever(key, (it, k) => it.ContainsKey(k));
		}
		public bool TryGetValue(K key, out V value)
		{
			var v = default(V);
			var exist = ForeachRever(key, (it, k) => it.TryGetValue(k, out v));
			value = v;
			return exist;
		}

		/// <summary>
		/// 清理list中所有的表
		/// </summary>
		public void Clear()
		{
			mTables.Clear();
		}

		/// <summary>
		/// 获取表中key的value
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public V this[K key]
		{
			get
			{
				return Get(key);
			}
		}
	}
}